import re

from django.contrib.auth.models import Permission, ContentType, Group
from django.db import transaction
from fdfs_client.client import Fdfs_client
from rest_framework import serializers
from apps.goods.models import GoodsVisitCount, SPUSpecification, SPU, SKUImage, SKU, SpecificationOption, GoodsCategory, \
    SKUSpecification, Brand, GoodsChannel, GoodsChannelGroup
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import User
from meiduo_mail import settings
from celery_tasks.static_html.tasks import get_detail_html


class GoodsSerializer(serializers.ModelSerializer):
    category = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = GoodsVisitCount
        fields = ('count', 'category')


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'email')


class UserAddSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        filed = ('id', 'username', 'password', 'email', 'mobile')
        extra_kays = {
            'username': {
                'max_length': 20,
                'min_length': 5
            },
            'passwork': {
                'max_length': 20,
                'min_length': 8,
                'write_only': True
            }
        }

    def validate_mobile(self, value):
        if not re.match('1[3-9]\d{9}', value):
            return serializers.ValidationError('格式不匹配')
        return value

    def create(self, validated_data):
        user = User.objects.create_user(**validated_data)
        return user


class SPUSpecificationSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()

    class Meta:
        model = SPUSpecification
        fields = '__all__'


class SPUSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        # fields = ('id', 'name')
        fields = '__all__'


class SKUImageSerializer(serializers.ModelSerializer):
    sku = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = SKUImage
        fields = '__all__'

    def create(self, validated_data):
        client = Fdfs_client(settings.FASRTDFS_PATH)
        request = self.context['request']
        image_file = request.data.get('image')
        res = client.upload_by_buffer(image_file.read())
        if res['Status'] != 'Upload successed.':
            raise serializers.ValidationError('图片上传失败')
        image_url = res['Remote file_id']
        img = SKUImage.objects.create(image=image_url, sku_id=request.data['sku'])
        return img

    def update(self, instance, validated_data):
        client = Fdfs_client(settings.FASRTDFS_PATH)
        request = self.context['request']
        image_file = request.data.get('image')
        res = client.upload_by_buffer(image_file.read())
        if res['Status'] != 'Upload successed.':
            raise serializers.ValidationError('图片上传失败')
        image_url = res['Remote file_id']
        instance.image = image_url
        instance.sku_id = request.data['sku']
        instance.save()
        sku = SKU.objects.get(id=request.data['sku'])
        if not sku.default_image:
            sku.default_image = image_url
            sku.save()
        get_detail_html.delay(request.data['sku'])
        return instance


class SKUSpecificationSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = ('spec_id', 'option_id')


class SKUSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    category = serializers.StringRelatedField(read_only=True)
    category_id = serializers.IntegerField()
    specs = SKUSpecificationSerializer(many=True)

    class Meta:
        model = SKU
        fields = '__all__'

    def create(self, validated_data):
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                specs = validated_data['specs']
                del validated_data['specs']
                sku = SKU.objects.create(**validated_data)
                # request = self.context['request']
                # specs = request.data['specs']
                for s in specs:
                    SKUSpecification.objects.create(sku=sku, spec_id=s['spec_id'], option_id=s['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('保存失败')
            transaction.savepoint_commit(save_point)
            get_detail_html.delay(sku.id)
            return sku

    def update(self, instance, validated_data):
        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                specs = validated_data['specs']
                del validated_data['specs']
                SKU.objects.filter(id=instance.id).update(**validated_data)
                for spec in specs:
                    SKUSpecification.objects.filter(sku=instance, spec_id=spec['spec_id']).update(
                        option_id=spec['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('保存失败')
            transaction.savepoint_commit(save_point)
            sku = SKU.objects.get(id=instance.id)
            get_detail_html.delay(sku.id)
            return sku


class GoodsCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = '__all__'


class SpecificationOptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = '__all__'


class SPUSpecificationSerializer2(serializers.ModelSerializer):
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    options = SpecificationOptionSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = '__all__'


class OrderGoodsSerializer(serializers.ModelSerializer):
    sku = SKUSerializer()

    class Meta:
        model = OrderGoods
        fields = ('count', 'price', 'sku')


class OrderInfoSerializer(serializers.ModelSerializer):
    user = serializers.StringRelatedField(read_only=True)
    user_id = serializers.IntegerField(read_only=True)
    skus = OrderGoodsSerializer(many=True)

    class Meta:
        model = OrderInfo
        fields = '__all__'


class PermissionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Permission
        fields = '__all__'


class ContentTypeSerializer(serializers.ModelSerializer):
    name = serializers.CharField(read_only=True)

    class Meta:
        model = ContentType
        fields = '__all__'


class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = '__all__'


class AdminSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {
            'password': {
                'write_only': True,
                'max_length': 20,
                'min_length': 8,
                'required': False,
            },
            'username': {
                'max_length': 20,
                'min_length': 5,
            }
        }

    def validate_mobile(self, value):
        if not re.match('1[3-9]\d{9}', value):
            raise serializers.ValidationError('手机格式不匹配')
        return value

    def create(self, validated_data):
        admin = super().create(validated_data)
        admin.set_password(validated_data['password'])
        admin.is_staff = True
        admin.save()
        return admin


class SPUSerializer2(serializers.ModelSerializer):
    brand = serializers.StringRelatedField(read_only=True)
    brand_id = serializers.IntegerField()
    category1_id = serializers.IntegerField()
    category2_id = serializers.IntegerField()
    category3_id = serializers.IntegerField()

    class Meta:
        model = SPU
        fields = '__all__'
        extra_kwargs = {
            'category1': {'required': False, },
            'category2': {'required': False, },
            'category3': {'required': False, }
        }


class BrandSerializer(serializers.ModelSerializer):
    class Meta:
        model = Brand
        fields = '__all__'


class SPUGoodsCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = '__all__'
        # exclude = ('parent',)


class SPUSpecSerializer(serializers.ModelSerializer):
    spec = serializers.StringRelatedField(read_only=True)
    spec_id = serializers.IntegerField()

    class Meta:
        model = SpecificationOption
        fields = '__all__'


class SPUSpecSerializer2(serializers.ModelSerializer):
    spu = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = SPUSpecification
        fields = ('id', 'name', 'spu')


class BrandSerializer2(serializers.ModelSerializer):
    class Meta:
        model = Brand
        fields = '__all__'

    def create(self, validated_data):
        client = Fdfs_client(settings.FASRTDFS_PATH)
        request = self.context['request']
        image_file = request.data.get('logo')
        res = client.upload_by_buffer(image_file.read())
        if res['Status'] != 'Upload successed.':
            raise serializers.ValidationError('图片上传失败')
        image_url = res['Remote file_id']
        img = Brand.objects.create(logo=image_url, name=request.data['name'], first_letter=request.data['first_letter'])
        return img

    def update(self, instance, validated_data):
        client = Fdfs_client(settings.FASRTDFS_PATH)
        request = self.context['request']
        image_file = request.data.get('logo')
        res = client.upload_by_buffer(image_file.read())
        if res['Status'] != 'Upload successed.':
            raise serializers.ValidationError('图片上传失败')
        image_url = res['Remote file_id']
        instance.logo = image_url
        instance.name = request.data['name']
        instance.first_letter = request.data['first_letter']
        instance.save()
        return instance


class GoodsChannelSerializer(serializers.ModelSerializer):
    group = serializers.StringRelatedField(read_only=True)
    group_id = serializers.IntegerField()
    category = serializers.StringRelatedField(read_only=True)
    category_id = serializers.IntegerField()

    class Meta:
        model = GoodsChannel
        fields = '__all__'
        # fields = ('id', 'group', 'category_id', 'category', 'group_id')


class GroupChannelSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsChannelGroup
        fields = '__all__'
